﻿namespace Bildverarbeitung.CGFilter
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using OpenSURFcs;
    using AForge;
    using AForge.Imaging;
    using System.Drawing.Imaging;
    using System.Drawing.Drawing2D;

    /// <summary>
    /// 
    /// </summary>
    public class RichardtManuelFilter : Bildverarbeitung.IFilter
    {
        /// <summary>
        /// Gets the summerized difference from average of all images.
        /// </summary>
        /// <param name="images">Given images.</param>
        /// <returns>The summerized difference.</returns>
        public Bitmap GetImageWithAllSurfFeatures(Bitmap[] images)
        {
            if (images == null || images.Length == 0)
            {
                throw new ArgumentNullException("Liste ist leer.");
            }
            double[] drehungDEG = new double[] { -1, 10, 20, 30, 45, 90, 135, 180, 0, 0, 0, 0, 0, 0 };

            float scaleWidth_Bild0 = images[8].Width / 2.0f;
            float scaleHeight_Bild0 = images[8].Height / 2.0f;
            List<IPoint>[] ipts = new List<IPoint>[images.Length];

            Parallel.For(0, images.Length, i =>
            {
                OpenSURFcs.IntegralImage iimg = OpenSURFcs.IntegralImage.FromImage(images[i]);
                ipts[i] = new List<IPoint>();
                ipts[i] = FastHessian.getIpoints(0.0002f, 5, 2, iimg);

                double drehungRAD = (drehungDEG[i] * (Math.PI / 180));
                float width2 = (images[i].Width) / 2.0f;
                float height2 = (images[i].Height) / 2.0f;

                if (drehungDEG[i] >= 0)
                {
                    for (int j = 0; j < ipts[i].Count; j++)
                    {
                        double sin = Math.Sin(drehungRAD);
                        double cos = Math.Cos(drehungRAD);

                        double term1 = ((ipts[i][j].x - width2) * cos);
                        double term2 = ((ipts[i][j].y - height2) * sin);

                        double term3 = ((ipts[i][j].x - width2) * sin);
                        double term4 = ((ipts[i][j].y - height2) * cos);

                        ipts[i][j].x = (float)(scaleWidth_Bild0 + (term1 - term2));
                        ipts[i][j].y = (float)(scaleHeight_Bild0 + (term3 + term4));
                    }
                }
                else
                {
                    // Punkte spiegeln
                    for (int j = 0; j < ipts[i].Count; j++)
                    {
                        ipts[i][j].x -= width2;
                        ipts[i][j].x = ipts[i][j].x * -1;
                        ipts[i][j].x += width2;
                    }
                }
            });
            Graphics g = Graphics.FromImage(images[8]);
            for (int a = 0; a < images.Length; a++)
            {
                float ergX = images[a].Width / images[8].Width;
                float ergY = images[a].Height / images[8].Height;
                
                for (int i = 0; i < ipts[a].Count; i++)
                {
                    int x = (int)(ipts[a][i].x);
                    int y = (int)(ipts[a][i].y);
                    g.FillRectangle(new SolidBrush(Color.FromArgb(25 ,255, 255, 255)), new Rectangle(x, y, 5, 5));                    
                }
            }
            return images[8];
        
        }

        /// <summary>
        /// Return the author´s name
        /// Please use NachnameVorname (without spaces).
        /// </summary>
        /// <returns>author´s name</returns>
        public String GetName()
        {
            return ("RichardtManuel");
        }
    }
}
